package com.ds;

import com.sun.syndication.io.SyndFeedInput;
import com.sun.syndication.io.XmlReader;
import com.sun.syndication.io.FeedException;
import com.sun.syndication.feed.synd.SyndFeed;
import com.sun.syndication.feed.synd.SyndEntryImpl;
import com.sun.syndication.feed.synd.SyndEnclosure;

import javax.xml.bind.annotation.*;
import javax.swing.tree.TreeNode;
import java.net.URL;
import java.net.MalformedURLException;
import java.io.IOException;
import java.util.*;
import java.util.logging.Logger;

/**
 * Created by IntelliJ IDEA.
 * User: daniel
 * Date: 28/10/2009
 * Time: 15:07:27
 */
@XmlType( name = "show" )
public class TVShow implements TreeNode {

    private static Logger logger = Logger.getLogger("rsstorrent");
    private static final int SEEDS_MINIMUM_THRESHOLD = 100;


    @XmlElement
    private String name;
    @XmlElement
    private String rssURL;
    @XmlElement
    private String filter;
    @XmlElement
    private String not;

    private Shows shows;
    private List<Episode> episodes;
    private boolean readOK;


    public String retrieveName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setRssURL(String rssURL) {
        this.rssURL = rssURL;
    }

    public void setShows(Shows shows) {
        this.shows = shows;
        for(Episode e: episodes){
            e.setShow(this);
        }
    }

    public void readFeed() throws FeedException, IOException {
        episodes = new ArrayList<Episode>();
        List<Episode> tempEpisodes = new ArrayList<Episode>();

        URL feedUrl = new URL(rssURL);

        SyndFeedInput input = new SyndFeedInput();
        SyndFeed feed = input.build(new XmlReader(feedUrl));

        List entries = feed.getEntries();
        for (Object entry : entries) {
            SyndEntryImpl syndEntry = (SyndEntryImpl) entry;
            Date episodeDate = syndEntry.getPublishedDate();
            if (episodeDate.after(TVShowsConfig.START_DATE)) {
                String title = syndEntry.getTitle();
                Episode episode = new Episode(syndEntry);
                /*"English".equals(episode.getLanguage()) && */
                if(episode.getSeedsCount()>SEEDS_MINIMUM_THRESHOLD)
                {
                    if(checkNotFilter(title)) {
                        episodes.add(episode);

                        if(checkFilter(title)) {
                            tempEpisodes.add(episode);
                        }
                    }
                }
            }
        }
        //if filter array is not empty use it
        if(!tempEpisodes.isEmpty()) {
            this.episodes = tempEpisodes;
        }
        Collections.sort(episodes, new Comparator<Episode>(){
            public int compare(Episode o1, Episode o2) {
                return o2.getSeedsCount() - o1.getSeedsCount();
//                return o1.getEpisodeDate().before(o2.getEpisodeDate()) ? -1 : 1;
            }
        });
        logger.info(this.name + " : " + episodes);
    }

    private boolean checkFilter(String title) {

        if(filter != null && filter.length()>0) {
            StringTokenizer st = new StringTokenizer(filter," ");
            while(st.hasMoreTokens()){
                String token = st.nextToken().toLowerCase();
                if(title.toLowerCase().indexOf(token) > -1) {
                    logger.fine("Filter: " + token + " | " + title);
                    return true;
                }
            }
        }
        return false;
    }

    private boolean checkNotFilter(String title) {
        StringTokenizer st = new StringTokenizer(not," ");
        while(st.hasMoreTokens()){
            String token = st.nextToken().toLowerCase();
            if(title.toLowerCase().indexOf(token) != -1) {
                logger.fine("notFilter: " + token + " | " + title);
                return false;
            }
        }
        return true;
    }

    public void setFilter(String filter) {
        this.filter = filter;
    }

    public void setNot(String not) {
        this.not = not;
    }

    public int getEpisodesCount(){
        return episodes.size();
    }

    public String toString() {
//        return "TVShow: [" + name + ',' + rssURL + ',' + filter + ',' + not +"]";
        return name; 
    }

    public Episode getEpisode(int index) {
        return episodes.get(index);
    }


    public boolean isReadOK() {
        return readOK;
    }

    public void setReadOK(boolean readOK) {
        this.readOK = readOK;
    }

    public List<? extends Episode> getAllEpisodes() {
        return episodes;
    }

    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        TVShow tvShow = (TVShow) o;

        if (name != null ? !name.equals(tvShow.name) : tvShow.name != null) return false;
        if (rssURL != null ? !rssURL.equals(tvShow.rssURL) : tvShow.rssURL != null) return false;

        return true;
    }

    public int hashCode() {
        int result;
        result = (name != null ? name.hashCode() : 0);
        result = 31 * result + (rssURL != null ? rssURL.hashCode() : 0);
        return result;
    }

    //TreeNode implementation

    public TreeNode getChildAt(int childIndex) {
        return episodes.get(childIndex);
    }

    public int getChildCount() {
        return episodes.size();
    }

    public TreeNode getParent() {
        return shows;
    }

    public int getIndex(TreeNode node) {
        return episodes.indexOf(node);
    }

    public boolean getAllowsChildren() {
        return true;
    }

    public boolean isLeaf() {
        return episodes.isEmpty();
    }

    public Enumeration children() {
        return Collections.enumeration(episodes);
    }
}
